#include "head.h"

void print_progress_bar(size_t total_received,size_t file_size){
    int width = 50;  // 进度条宽度
    float progress = (float)total_received / file_size;
    int pos = width * progress;

    printf("\r[");
    for (int i = 0; i < width; ++i) {
        if (i < pos) printf("=");
        else if (i == pos) printf(">");
        else printf(" ");
    }
    printf("] %5.2f%%", (progress * 100));
    usleep(10000);
    fflush(stdout);
}

data_t send_to_server_msg(int sockfd, char *file_name, char *method){
    data_t file_detail; //获取文件名长度和文件名
    memset(&file_detail,0,sizeof(file_detail));

    file_detail.len = strlen(method); //计算传输方法的长度
    memcpy(file_detail.msg,method,file_detail.len); //获取文件传输的方法
    //将传输方法发送给服务器
    send(sockfd,&file_detail,sizeof(int) + file_detail.len,MSG_NOSIGNAL); 

    memset(&file_detail,0,sizeof(file_detail));
    file_detail.len = strlen(file_name);
    memcpy(file_detail.msg,file_name,file_detail.len);
    //将文件名发送给服务端
    send(sockfd,&file_detail,sizeof(int) + file_detail.len,MSG_NOSIGNAL);
    return file_detail;
}

int upload_file(int sockfd,char *file_name,char *method){
    data_t file_detail = send_to_server_msg(sockfd,file_name,method);
    //首先打开一个文件
    int file_fd = open(file_name,O_RDONLY);
    ERROR_CHECK(file_fd,-1,"open");
    //获取该文件的大小
    struct stat file_data;
    fstat(file_fd,&file_data);

    //把文件大小发给服务端
    send(sockfd,&file_data.st_size,sizeof(off_t),MSG_NOSIGNAL);

    size_t recveied_total = 0; //已发送的字节数
    size_t chunk_size = 1024; //每次读取的字节数
    size_t file_size = file_data.st_size; //总字节数
    char buf[1024];
    while(recveied_total < file_size){
        //计算当前应该读取的字节数
        size_t cur_read_size = (file_size - recveied_total) < chunk_size ? (file_size - recveied_total) : chunk_size;
        memset(buf,0,sizeof(buf));
        // size_t read_size = recv(sockfd,p+recveied_total,cur_read_size,MSG_WAITALL);
        //从磁盘中读取指定字节数到buf中
        size_t read_size = read(file_fd,buf,cur_read_size);
        ERROR_CHECK(read_size,-1,"read");
        if(read_size == 0){
            //文件已读完
            break;
        }
        //将读取的字节数发送到服务端
        send(sockfd,buf,read_size,MSG_NOSIGNAL);
        recveied_total += read_size;
        print_progress_bar(recveied_total,file_size);
    }
    printf("\n");
    printf("upload success...\n");
    close(file_fd);
    return 0;
}

int download_file(int sockfd,char *file_name,char *method){
    data_t file_detail = send_to_server_msg(sockfd,file_name,method);

    //通过文件名打开并创建一个文件
    int file_fd = open(file_detail.msg,O_RDWR | O_CREAT,0666);
    ERROR_CHECK(file_fd,-1,"open");

    off_t file_size = 0;
    //接收文件的大小
    recv(sockfd,&file_size,sizeof(off_t),MSG_WAITALL);
    printf("file_size : %ld \n",file_size);
    ftruncate(file_fd,file_size);

    //做文件映射
    void *p = mmap(NULL,file_size,PROT_READ | PROT_WRITE,MAP_SHARED,file_fd,0);

    size_t recveied_total = 0; //已读取的字节数
    size_t chunk_size = 1024; //每次读取的字节数
    while(recveied_total < file_size){
        //计算当前应该读取的字节数
        size_t cur_read_size = (file_size - recveied_total) < chunk_size ? (file_size - recveied_total) : chunk_size;
        size_t read_size = recv(sockfd,p+recveied_total,cur_read_size,MSG_WAITALL);
        if(read_size == 0){
            //发送方关闭连接且无数据可读
            break;
        }
        recveied_total += read_size;
        print_progress_bar(recveied_total,file_size);
    }
    printf("\n");
    printf("download success...\n");
    munmap(p,file_size);
    close(file_fd);
    return 0;
}